package net.yla.smartbus.core.wechat;

//import net.sf.json.JSONObject;

import com.alibaba.fastjson.JSONObject;
import net.yla.smartbus.core.api.RequestCode;
import net.yla.smartbus.core.exception.AppException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author wangpan
 * @date 2018/6/3 22:37
 */
@RestController
@RequestMapping(value = "/wechat")
public class WeixinUtil {
    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {(TrustManager) new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);
            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpUrlConn.connect();
            }
            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Weixin server connection timed out.");
        } catch (Exception e) {
            log.error("https request error:{}", e);
        }
        return jsonObject;
    }

    /**
     * 自定义getParameter方法，baseCOntroller里也有，此处因为要移除code和state，
     */
    public static String getParameters(HttpServletRequest request) {
        String str = "";
        Map<String, String[]> map = request.getParameterMap();// 获取参数Map
        Set<Map.Entry<String, String[]>> keSet = map.entrySet();
        String value = "";

        Iterator<Map.Entry<String, String[]>> iterator = keSet.iterator();// 遍历参数
        while (iterator.hasNext()) {
            Map.Entry<String, String[]> entry = iterator.next();
            String ok = entry.getKey();// 键名
            String[] ov = entry.getValue();// 键值

            if (!"code".equals(ok) && !"state".equals(ok)) {// 去除code和state参数
                if (null == ov) {
                    value = "";
                } else {
                    for (int i = 0; i < ov.length; i++) {
                        value = ov[i] + "|";
                    }
                    value = value.substring(0, value.length() - 1);
                }

                if (!"oper".equals(ok)) {
                    str += ok + "=" + value + "&";
                }
            }
        }
        if (str.endsWith("&")) {
            str = str.substring(0, str.length() - 1);
        }
        return str;
    }

    /**
     * 微信重定向跳转
     *
     * @param response
     * @param params
     * @param appId
     * @param purl
     */
    public static void toWechatUserInfo(HttpServletResponse response, String params, String appId, String purl) {
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI" +
                "&response_type=code&scope=SCOPE&state=STATE&connect_redirect=1#wechat_redirect";
        url = url.replace("APPID", appId);

        log.info("==============>" + params);
        // param格式  如 appid=sajdasdfkas
        if (StringUtils.isNotBlank(params)) {
            purl = purl + "?" + params;
        }
        try {
            purl = java.net.URLEncoder.encode(purl, "utf-8");
        } catch (UnsupportedEncodingException e) {
            log.error("微信扫码登录重定向地址转码失败:e{}", e);
            throw new AppException("地址转码失败", RequestCode.forbid_error);
        }
        url = url.replace("REDIRECT_URI", purl);
        url = url.replace("SCOPE", "snsapi_userinfo");
        // url = url.replace("SCOPE", "snsapi_base");
        url = url.replace("STATE", "123");
        log.info("===========  xia  ===url==============" + url);

        try {
            response.sendRedirect(url);
        } catch (IOException e) {
            log.error("微信扫码登录重定向response失败, e{}", e);
            throw new AppException("重定向失败", RequestCode.forbid_error);
        }
    }

    /**
     * 根据APPId和secret 获取token
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public static String getAccessToken(String appId, String appSecret) {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
        JSONObject json = httpRequest(url, "GET", null);
        log.info("json信息========>：" + json.toString());
        String access_token = null;
        if (json != null) {
            access_token = json.getString("access_token");
        }
        return access_token;
    }

    /**
     * 根据access_token获取 jsapi_ticket
     *
     * @param access_token
     * @return
     */
    public static String getJsApiTicket(String access_token) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";
        JSONObject json = httpRequest(url, "GET", null);
        String jsapi_ticket = null;
        if (json != null) {
            jsapi_ticket = json.getString("ticket");
        }
        return jsapi_ticket;
    }

    /**
     * 获取微信签名 jssdk
     *
     * @param str
     * @return
     */
    public static String getSignature(String str) {
        String signature = null;
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            signature = WeixinUtil.byteToHex(crypt.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signature;
    }

    /**
     * 获取微信卡券的ticket
     *
     * @param access_token
     * @return
     */
    public static String getCardApiTicket(String access_token) {
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", access_token);
        JSONObject jsonObject4Card = httpRequest(requestUrl, "GET", null);
        log.info("----jsonObject4Card------" + jsonObject4Card);
        String api_ticket = null;
        if (jsonObject4Card != null) {
            api_ticket = jsonObject4Card.getString("ticket");
        }
        return api_ticket;
    }


    /**
     * 随机加密
     *
     * @param hash
     * @return
     */
    public static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 根据code查询微信用户基础信息
     *
     * @param code
     * @param appId
     * @param appSecret
     * @return
     */
    public static SNSUserInfo fillUserInfo(String code, String appId, String appSecret) {
        SNSUserInfo snsUserInfo = null;
        log.info("fillUserInfo()+++++++++++++++++++++++++++++    appId----appId==：" + appId + "----------appSecret===" + appSecret + "============code==:" + code);
        String openid = "";

        if (!"authdeny".equals(code)) {
            WeixinOauth2Token wot = null;
            if (code != null) {
                wot = Oauth2Util.getOauth2AccessToken(appId, appSecret, code);
                if (wot == null) {
                    //code过期，
                    return null;
                }
                openid = wot.getOpenId();
                snsUserInfo = Oauth2Util.getSNSUserInfo(wot.getAccessToken(), openid);
                log.info("fillUserInfo()+++++++++++++++++++++++++++++  openid==：" + openid);
            }
            log.info("weixin   +++++++++++++++++++++++++++++++++    openid________________________________openid==：" + openid);
        }
        log.info("function:snsUserInfo======fillUserInfo(){}", snsUserInfo.toString());
        return snsUserInfo;
    }
}
